#pragma once
#include "windows.h"
#include "GSE_Log.h"
#include "GSE_Net.h"
#include <ostream>
void output_memory_alloc(std::ostream& os);

using namespace GSE;
struct Fixture
{
	Fixture()
	{
		INet::CreateModule(false);
	}
	~Fixture()
	{
		INet::DestroyModule();
		//output_memory_alloc(std::cout);
	}
};

class CServer
{
public:
	void Init()
	{
		m_bShutdown = false;
		m_lpMgr = NULL;
		m_lpListener =  INet::InstancePtr()->CreateListener();
	}
	void Listen(const char * strIP,const char * strPort)
	{
		m_lpListener->AsyncListen(strIP,strPort);
	}
	void Uninit()
	{
		m_lpListener->SetSessionManager(NULL);
		INet::InstancePtr()->DestroyListener(m_lpListener);
		delete m_lpMgr;

	}
	static CServer& Instance()
	{
		static CServer obj;
		return obj;
	}
	void SetMgr(ISessionManager * lpMgr)
	{
		m_lpListener->SetSessionManager(lpMgr);
		m_lpMgr = lpMgr;
	}
	void Shutdown()
	{
		m_bShutdown = true;
	}
	void run()
	{
		while ( !m_bShutdown )
		{
			m_lpListener->Run();
		}
	}
private:
	ISessionManager * m_lpMgr;
	IListener * m_lpListener;
	bool m_bShutdown;
};



class CClient_1
{
public:
	void Init()
	{
		m_bShutdown = false;
		m_lpConnector = INet::InstancePtr()->CreateConnector();
	}
	void SetCallback(ISessionCallback * lpCB)
	{
		m_lpConnector->SetSessionCallback(lpCB);
	}
	ISession * GetSession()
	{
		return m_lpConnector->GetSession();
	}

	void Connect(const char* strIP,const char * strPort)
	{
		m_lpConnector->Connect(strIP,strPort);
	}
	void Run()
	{
		while ( !m_bShutdown )
		{
			m_lpConnector->Run();
		}		
	}
	void Uninit()
	{
		delete m_lpConnector->GetSession()->GetCallbackPtr();
		INet::InstancePtr()->DestroyConnector(m_lpConnector);
	}
	void Shutdown()
	{
		m_bShutdown = true;
	}
private:
	IConnector * m_lpConnector;
	bool	m_bShutdown;
};



class CClientCallback_2 : public ISessionCallback
{
public:
	CClientCallback_2(CClient_1 * lp,int i):lpClient(lp),m_lpSession(lpClient->GetSession()),m_I(i) {}
	virtual void OnConnected()
	{
		std::string bb = "Hello,I am the : ";
		bb += m_I;
		for ( int i = 0 ; i < 100; i ++ )
		{
			m_lpSession->Send(bb.c_str(),bb.size());
			Sleep(10);
		}

		std::string bye = "Bye";
		m_lpSession->Send(bye.c_str(),bye.size());
	}
	virtual void OnReceive(const char * lpBuffer, uint32 uLen)
	{
		if ( memcmp(lpBuffer,"Bye",3) == 0)
		{
			lpClient->Shutdown();
			m_lpSession->Close();
			return;
		}
	}
	virtual void OnError(int errCode,const char * errMsg)
	{
		LOG(LOG_GSE_CRITICAL) << errMsg;
		BOOST_CHECK(0);
	}
	virtual void OnDisconnected()
	{
		BOOST_CHECK(0);
	}
protected:
	CClient_1 * lpClient;
	ISession * m_lpSession;
	int m_I;
};

class CServerCallback_2 : public ISessionCallback
{
public:
	CServerCallback_2(ISession * lpSession):m_lpSession(lpSession){}

	virtual void OnReceive(const char * lpBuffer, uint32 uLen)
	{
		if ( memcmp(lpBuffer,"Bye",3) == 0)
		{
			m_lpSession->Send("Bye",3);
			return;
		}
		((char*)lpBuffer)[uLen] = 0;
		LOG(LOG_GSE_CRITICAL) << lpBuffer;
	}
	virtual void OnConnected()
	{
		LOG(LOG_GSE_CRITICAL) << __FUNCTION__ ;
	}
	virtual void OnDisconnected()
	{
		BOOST_CHECK(0);
	}

	virtual void OnError(int errCode,const char * errMsg)
	{
		LOG(LOG_GSE_CRITICAL) << errMsg;
	}


protected:
	ISession * m_lpSession;

};


class CServerSessionMgr_2: public ISessionManager
{
public:
	virtual void OnAccept(ISession * lpSession)
	{
		lpSession->SetCallback(new CServerCallback_2(lpSession));
		m_Sessions.insert(lpSession);
	}
	virtual void OnCloseSession(ISession * lpSession)
	{
		delete lpSession->GetCallbackPtr();
		m_Sessions.erase(lpSession);
	}
	virtual void Release()
	{
		delete this;
	}
protected:
	std::set<ISession *> m_Sessions;
};